﻿#pragma once
#include "../logger.h"
#include "loghand.h"

#include <ostream>
#include <streambuf>

NAMESPACE_BEG

class LoggerImpl :public std::ostream, public std::stringbuf {

public:
	LoggerImpl(LogProper&& proper) : std::ostream(this), proper_(std::move(proper)) { buffer_.reserve(128); }
	LoggerImpl() : std::ostream(this) { buffer_.reserve(128); }
	~LoggerImpl() {}
	void setProper(LogProper&& proper) { proper_ = std::move(proper); }
	const ErrorTrace& getLastError() {
		return trac_;
	}
	
protected:
	int overflow(int ch) override
	{
		if (ch == 'E'&& !trigger_cnt_) {
			trigger_cnt_++;
		}
		else if (trigger_cnt_ && (ch == 'N' || ch == 'D'))
		{
			if (++trigger_cnt_ >= 3) {
				trigger_cnt_ = 0;
				for (int i = 0; i < 2; i++)buffer_.pop_back();
				__send();
				return buffer_.size();
			}
		}
		else if (trigger_cnt_) {
			trigger_cnt_ = 0;
		}
		
		buffer_.push_back(ch);
		return buffer_.size();
	}



	void __send() {
		LogItem item;
		item.property_ = std::move(proper_);
		item.log_ = std::move(std::string(buffer_.begin(), buffer_.end()));
		if (item.property_.level_ & LOG_LEVEL::ERR) {
			trac_.file_ = item.property_.file_;
			trac_.fun_ = item.property_.func_;
			trac_.line_ = item.property_.line_;
			trac_.log_ = item.log_;
			trac_.thrad_id_ = (uint64_t)item.property_.thread_id_;
			trac_.time_ = item.property_.time_.time_since_epoch().count();
		}
		buffer_.clear();
		LoggerPrintMgr::getInstance().postLog(std::move(item));
	}

private:
	int         trigger_cnt_ = 0;
	ErrorTrace  trac_;
	LogProper   proper_;
	LOG_LEVEL   level_;
	std::vector<char> buffer_;
};
NAMESPACE_END
